﻿using System;
using System.Diagnostics.Contracts;

namespace Postnuclear
  {
  /// <summary>
  /// The extension methods for the <see cref="INotifyValueChanged"/>.
  /// </summary>  
  public static partial class ExtensionMethods
    {
    #region Public

    // Methods

    /// <summary>
    /// Observes the specified <see cref="INotifyValueChanged"/> and executes the specified handler when value is changed.
    /// </summary>
    /// <param name="observer">The value observer.</param>
    /// <param name="handler">The change handler.</param>
    /// <remarks>
    /// References the handler with weak reference, doesn't require un-subscription to allow listener to be garbage collected.
    /// </remarks>
    public static void Changed(this INotifyValueChanged observer, EventHandler<EventArgs> handler)
      {
      Contract.Requires<ArgumentNullException>(observer != null);
      Contract.Requires<ArgumentNullException>(handler != null);

      observer.ValueChanged += handler.MakeWeak(eh => observer.ValueChanged -= eh);
      }

    /// <summary>
    /// Observes the specified <see cref="IValueProvider{TValue}"/> and executes the specified handler when value is changed.
    /// </summary>
    /// <typeparam name="TValue">The type of the value.</typeparam>
    /// <param name="observer">The value observer.</param>
    /// <param name="handler">The change handler.</param>
    /// <remarks>
    /// References the handler with weak reference, doesn't require un-subscription to allow listener to be garbage collected.
    /// </remarks>
    public static void Changed<TValue>(this IValueProvider<TValue> observer, EventHandler<ValueEventArgs<TValue>> handler)
      {
      Contract.Requires<ArgumentNullException>(observer != null);
      Contract.Requires<ArgumentNullException>(handler != null);

      ValueProviderAdapter<TValue> adapter = new ValueProviderAdapter<TValue>(observer);
      adapter.ValueChanged += handler.MakeWeak(eh => adapter.ValueChanged -= eh);
      }

    #endregion
    }
  }